package com.ruoyi.park.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.omp.api.enums.WarehouseRecordTypeEnum;
import com.ruoyi.park.domain.MaHouseMaterial;
import com.ruoyi.park.domain.MaInOutRecord;
import com.ruoyi.park.domain.MaMaterial;
import com.ruoyi.park.domain.MaRecordDetail;
import com.ruoyi.park.mapper.MaHouseMaterialMapper;
import com.ruoyi.park.mapper.MaInOutRecordMapper;
import com.ruoyi.park.mapper.MaMaterialMapper;
import com.ruoyi.park.mapper.MaRecordDetailMapper;
import com.ruoyi.park.service.IMaInOutRecordService;
import com.ruoyi.system.api.RemoteBmCodeService;
import com.ruoyi.system.api.domain.RemoteSysBmType;
import com.ruoyi.system.api.enums.SysBmCodeTypeValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 出入库记录Service业务层处理
 *
 * @author cjie
 * @date 2021-09-16
 */
@Service
public class MaInOutRecordServiceImpl implements IMaInOutRecordService {
    @Autowired
    private MaInOutRecordMapper maInOutRecordMapper;
    @Autowired
    private MaRecordDetailMapper maRecordDetailMapper;
    @Autowired
    private MaHouseMaterialMapper maHouseMaterialMapper;
    @Autowired
    private MaMaterialMapper maMaterialMapper;
    @Autowired
    private RemoteBmCodeService remoteBmCodeService;

    @Autowired
    private RedisService redisService;

    /**
     * 查询出入库记录
     *
     * @param id 出入库记录ID
     * @return 出入库记录
     */
    @Override
    public MaInOutRecord selectMaInOutRecordById(String id) {
        MaInOutRecord maInOutRecord = maInOutRecordMapper.selectMaInOutRecordById(id);
        List<MaMaterial> materialList = maMaterialMapper.selectMaMaterialByRecordId(id);

        maInOutRecord.setMaMaterialList(materialList);
        return maInOutRecord;
    }

    /**
     * 查询出入库记录列表
     *
     * @param maInOutRecord 出入库记录
     * @return 出入库记录
     */
    @Override
    public List<MaInOutRecord> selectMaInOutRecordList(MaInOutRecord maInOutRecord) {
        return maInOutRecordMapper.selectMaInOutRecordList1(maInOutRecord);
    }

    /**
     * 新增出入库记录
     *
     * @param maInOutRecord 出入库记录
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized AjaxResult insertMaInOutRecord(MaInOutRecord maInOutRecord) {
        maInOutRecord.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
        maInOutRecord.setCreateTime(DateUtils.getNowDate());
        maInOutRecord.setCreateBy(SecurityUtils.getUsername());
        maInOutRecord.setRecordNumber(this.genRecordNumber(maInOutRecord.getRecordType()));
        if(maInOutRecord.getOperateTime() == null){
            maInOutRecord.setOperateTime(maInOutRecord.getCreateTime());
        }

        if(maInOutRecord.getMaMaterialList() != null && maInOutRecord.getMaMaterialList().size()>0){

            //入库和盘库时，选择列表中没有的物资新增
            for(MaMaterial maMaterial: maInOutRecord.getMaMaterialList()) {
                //如果物资id为空，并且物资名称+类别+规格 唯一，则为新增物资
                if(StringUtils.isEmpty(maMaterial.getId())){
                    MaMaterial source = maMaterialMapper.selectMaterialByNameStandardsAndCategory(maMaterial);
                    if(source == null){
                        maMaterial.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
                        maMaterial.setCreateTime(DateUtils.getNowDate());
                        maMaterial.setCreateBy(SecurityUtils.getUsername());
                        RemoteSysBmType remoteSysBmTyp = remoteBmCodeService.genGoodsCode(maMaterial.getCategory(), maMaterial.getMaterialName());
                        maMaterial.setMaterialNum(remoteSysBmTyp.getNowCode());
                        maMaterialMapper.insertMaMaterial(maMaterial);
                    }else{
                        maMaterial.setId(source.getId());
                    }

                }

                //修改库中的物资单价
                maMaterialMapper.updateMaMaterial(maMaterial);
            }

            if(WarehouseRecordTypeEnum.出库.getCode().equals(maInOutRecord.getRecordType())){
                for(MaMaterial maMaterial: maInOutRecord.getMaMaterialList()){
                    MaHouseMaterial maHouseMaterial =
                            maHouseMaterialMapper.selectMaHouseMaterialByHouseIdAndMaterialId(maInOutRecord.getWarehouseId(),maMaterial.getId());

                    if(maHouseMaterial == null || maHouseMaterial.getQuantity()< maMaterial.getQuantity()){
                        return AjaxResult.error("库存不足");
                    }else{
                        maHouseMaterial.setQuantity(maHouseMaterial.getQuantity()-maMaterial.getQuantity());
                        maHouseMaterialMapper.updateMaHouseMaterial(maHouseMaterial);
                    }

                    insertRecordDetail(maInOutRecord, maMaterial,0d);
                }
            }else{
                //入库和盘库对应库存中不存在的物资都需要新增
                for(MaMaterial maMaterial: maInOutRecord.getMaMaterialList()){
                    //入库时，如果对应仓库已存在物资，数量增加，没有直接新增
                    //盘库时，如果对应厂库已存在物资，数量变更，没有直接新增
                    MaHouseMaterial maHouseMaterial =
                            maHouseMaterialMapper.selectMaHouseMaterialByHouseIdAndMaterialId(maInOutRecord.getWarehouseId(),maMaterial.getId());
                    //盘前数量
                    Double oldQuantity = 0d;
                    if(maHouseMaterial == null){
                        maHouseMaterial = new MaHouseMaterial();
                        maHouseMaterial.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
                        maHouseMaterial.setHouseId(maInOutRecord.getWarehouseId());
                        maHouseMaterial.setMaterialId(maMaterial.getId());
                        maHouseMaterial.setQuantity(maMaterial.getQuantity());

                        maHouseMaterialMapper.insertMaHouseMaterial(maHouseMaterial);
                    }else{
                        if(WarehouseRecordTypeEnum.入库.getCode().equals(maInOutRecord.getRecordType())){
                            maHouseMaterial.setQuantity(maHouseMaterial.getQuantity()+maMaterial.getQuantity());
                        }else{
                            oldQuantity = maHouseMaterial.getQuantity();
                            maHouseMaterial.setQuantity(maMaterial.getQuantity());
                        }
                        maHouseMaterialMapper.updateMaHouseMaterial(maHouseMaterial);
                    }

                    //新增记录详情
                    insertRecordDetail(maInOutRecord, maMaterial,oldQuantity);
                }
            }
        }else{
            return AjaxResult.error("请选择物资");
        }

        AjaxResult result = maInOutRecordMapper.insertMaInOutRecord(maInOutRecord) > 0 ? AjaxResult.success() : AjaxResult.error();
        //入库时选择出库，进行出库
        if(WarehouseRecordTypeEnum.入库.getCode().equals(maInOutRecord.getRecordType()) && maInOutRecord.getIsOut().equals("1")){
            maInOutRecord.setRecordType(WarehouseRecordTypeEnum.出库.getCode());
            maInOutRecord.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
            maInOutRecord.setRecordNumber(this.genRecordNumber(maInOutRecord.getRecordType()));
            for(MaMaterial maMaterial: maInOutRecord.getMaMaterialList()){
                MaHouseMaterial maHouseMaterial =
                        maHouseMaterialMapper.selectMaHouseMaterialByHouseIdAndMaterialId(maInOutRecord.getWarehouseId(),maMaterial.getId());
                 maHouseMaterial.setQuantity(maHouseMaterial.getQuantity()-maMaterial.getQuantity());
                 maHouseMaterialMapper.updateMaHouseMaterial(maHouseMaterial);
                insertRecordDetail(maInOutRecord, maMaterial,0d);
            }
            maInOutRecordMapper.insertMaInOutRecord(maInOutRecord);
        }
        return result;
    }

    private String genRecordNumber(String type) {
        String date = DateUtil.format(DateUtil.date(), "yyyyMMdd");
        Integer v = redisService.getCacheObject(date);

        String result = "";
        if (v == null) {
            v = 0;
            redisService.setCacheObject(date, v,24L, TimeUnit.HOURS);
        }else {
            v = v + 1;
            redisService.setCacheObject(date, v);
        }
        String fs = String.format("%03d", v);
        switch (type){
            case "0" :
                result = "IM" + date + fs;
                break;
            case "1":
                result = "OM" + date + fs;
                break;
            case "2":
                result = "CM" + date + fs;
                break;
        }
        return result;
    }

    private void insertRecordDetail(MaInOutRecord maInOutRecord, MaMaterial maMaterial,Double oldQuantity) {
        MaRecordDetail maRecordDetail = new MaRecordDetail();
        maRecordDetail.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
        maRecordDetail.setRecordId(maInOutRecord.getId());
        maRecordDetail.setMaterialId(maMaterial.getId());
        maRecordDetail.setQuantity(maMaterial.getQuantity());

        //盘前数量
        maRecordDetail.setOldQuantity(oldQuantity);
        //盘后数量
        maRecordDetail.setNowQuantity(maMaterial.getQuantity());
        maRecordDetailMapper.insertMaRecordDetail(maRecordDetail);
    }

    /**
     * 修改出入库记录
     *
     * @param maInOutRecord 出入库记录
     * @return 结果
     */
    @Override
    public int updateMaInOutRecord(MaInOutRecord maInOutRecord) {
        maInOutRecord.setUpdateTime(DateUtils.getNowDate());
        maInOutRecord.setUpdateBy(SecurityUtils.getUsername());
        return maInOutRecordMapper.updateMaInOutRecord(maInOutRecord);
    }

    /**
     * 批量删除出入库记录
     *
     * @param ids 需要删除的出入库记录ID
     * @return 结果
     */
    @Override
    public int deleteMaInOutRecordByIds(String[] ids) {
        Arrays.stream(ids).forEach(recordId->{
            maRecordDetailMapper.deleteMaRecordDetailByRecordId(recordId);
        });
        return maInOutRecordMapper.deleteMaInOutRecordByIds(ids);
    }

    /**
     * 删除出入库记录信息
     *
     * @param id 出入库记录ID
     * @return 结果
     */
    @Override
    public int deleteMaInOutRecordById(String id) {
        return maInOutRecordMapper.deleteMaInOutRecordById(id);
    }
}
